package edu.vt.ece.rt.benchmark.genome;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.Random;

public class Segments {

    long length;
    long minNum;
    ArrayList<String> contentsPtr;
    /* private: */
    ArrayList<String> strings;
    
    public Segments(int length, int min) {
    	strings = new ArrayList<String>(min);
    	Random r = new Random();
    	for (int i = 0; i < min; i++) {
    		String curr = "";// generate random string of length
    		strings.set(i, curr);
    	}
    }
    
    /* =============================================================================
     * segments_create
     * -- Populates 'contentsPtr'
     * =============================================================================
     */
    public static void
    segments_create (Segments segmentsPtr, Gene genePtr, Random randomPtr)
    {
        ArrayList<String> segmentsContentsPtr;
        ArrayList<String> strings;
        int segmentLength;
        long minNumSegment;
        String geneString;
        long geneLength;
        HashMap<Integer, Integer> startBitmapPtr;
        long numStart;
        int i;
        long maxZeroRunLength;

        segmentsContentsPtr = segmentsPtr.contentsPtr;
        strings = segmentsPtr.strings;
        segmentLength = (int)segmentsPtr.length;
        minNumSegment = segmentsPtr.minNum;

        geneString = genePtr.contents;
        geneLength = genePtr.length;
        startBitmapPtr = genePtr.startBitmapPtr;
        numStart = geneLength - segmentLength + 1;

        /* Pick some random segments to start */
        for ( i = 0; i < minNumSegment; i++) {
            long j = (long)(randomPtr.nextLong() % numStart);
            startBitmapPtr.put(i, 1);
            strings.set(i, geneString.substring((int)j, (int)segmentLength));
            segmentsContentsPtr.add(strings.get(i));
        }

        /* Make sure segment covers start */
        i = 0;
        if (startBitmapPtr.get(new Integer(i)).intValue() == 0) {
        	String string = geneString.substring(i, segmentLength);
        	segmentsContentsPtr.add(string);
        	startBitmapPtr.put(i, 0);
        }

        /* Add extra segments to fill holes and ensure overlap */
        maxZeroRunLength = segmentLength - 1;
        for (i = 0; i < numStart; i++) {
            long i_stop = Math.min((i+maxZeroRunLength), numStart);
            for ( /* continue */; i < i_stop; i++) {
                if (startBitmapPtr.get(i).intValue() == 1) {
                    break;
                }
            }
            
            if (i == i_stop) {
                /* Found big enough hole */
                i = i - 1;
                String string = geneString.substring(i, segmentLength);
                segmentsContentsPtr.add(string);
                startBitmapPtr.put(i, 1);
            }
        }
    }

    static void
    tester (int geneLength, int segmentLength, int minNumSegment, boolean doPrint)
    {
        Gene genePtr;
        Segments segmentsPtr;
        Random randomPtr;
        HashMap<Integer,Integer> startBitmapPtr = new HashMap<Integer, Integer>();
        int i;
        int j;

        genePtr = new Gene(geneLength);
        segmentsPtr = new Segments(segmentLength, minNumSegment);
        randomPtr = new Random();
        
        Gene.gene_create(genePtr, randomPtr);
        Segments.segments_create(segmentsPtr, genePtr, randomPtr);

//        if (doPrint) {
//            printf("Gene = %s\n", genePtr->contents);
//        }

        /* Check that each segment occurs in gene */
        for (i = 0; i < segmentsPtr.contentsPtr.size(); i++) {
        	
        	String charPtr = segmentsPtr.contentsPtr.get(i);
            int index = genePtr.contents.indexOf(charPtr);
            
            j = charPtr.charAt(0) - genePtr.contents.charAt(0);
            startBitmapPtr.put(j, 1);
        }

        /* Check that there is complete overlap */
        for (i = 0, j = 0; i < geneLength; i++ ) {
            if (startBitmapPtr.get(i).intValue() == 1) {
               assert((i-j-1) < segmentLength);
               j = i;
            }
        }

    }

}
